This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

source("./tianfengRwrappers.R")
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
载入需要的程辑包:dplyr

载入程辑包:‘dplyr’

The following object is masked from ‘package:xgboost’:

    slice

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

载入需要的程辑包:reticulate
载入需要的程辑包:tidyr

载入程辑包:‘tidyr’

The following objects are masked from ‘package:Matrix’:

    expand, pack, unpack


载入程辑包:‘MySeuratWrappers’

The following objects are masked from ‘package:Seurat’:

    DimPlot, DoHeatmap, LabelClusters, RidgePlot, VlnPlot


载入程辑包:‘cowplot’

The following object is masked from ‘package:ggpubr’:

    get_legend

载入需要的程辑包:viridisLite

载入程辑包:‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths

NOTE: Either Arial Narrow or Roboto Condensed fonts are required to use these themes.
      Please use hrbrthemes::import_roboto_condensed() to install Roboto Condensed and
      if Arial Narrow is not on your system, please see https://bit.ly/arialnarrow

Registered S3 method overwritten by 'enrichplot':
  method               from
  fortify.enrichResult DOSE
clusterProfiler v3.14.3  For help: https://guangchuangyu.github.io/software/clusterProfiler

If you use clusterProfiler in published research, please cite:
Guangchuang Yu, Li-Gen Wang, Yanyan Han, Qing-Yu He. clusterProfiler: an R package for comparing biological themes among gene clusters. OMICS: A Journal of Integrative Biology. 2012, 16(5):284-287.
Registering fonts with R

载入程辑包:‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:xgboost’:

    slice

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout

载入需要的程辑包:Biobase
载入需要的程辑包:BiocGenerics
载入需要的程辑包:parallel

载入程辑包:‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ, clusterExport, clusterMap, parApply,
    parCapply, parLapply, parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:dplyr’:

    combine, intersect, setdiff, union

The following object is masked from ‘package:Matrix’:

    which

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated,
    eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match,
    mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames,
    sapply, setdiff, sort, table, tapply, union, unique, unsplit, which, which.max, which.min

Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
    'citation("Biobase")', and for packages 'citation("pkgname")'.

载入需要的程辑包:e1071

载入程辑包:‘widgetTools’

The following object is masked from ‘package:dplyr’:

    funs


载入程辑包:‘DynDoc’

The following object is masked from ‘package:BiocGenerics’:

    path


载入程辑包:‘DT’

The following object is masked from ‘package:Seurat’:

    JS

载入需要的程辑包:S4Vectors
载入需要的程辑包:stats4

载入程辑包:‘S4Vectors’

The following object is masked from ‘package:plotly’:

    rename

The following object is masked from ‘package:tidyr’:

    expand

The following objects are masked from ‘package:dplyr’:

    first, rename

The following object is masked from ‘package:Matrix’:

    expand

The following object is masked from ‘package:base’:

    expand.grid

载入需要的程辑包:IRanges

载入程辑包:‘IRanges’

The following object is masked from ‘package:plotly’:

    slice

The following objects are masked from ‘package:dplyr’:

    collapse, desc, slice

The following object is masked from ‘package:xgboost’:

    slice

载入需要的程辑包:GenomicRanges
载入需要的程辑包:GenomeInfoDb
载入需要的程辑包:SummarizedExperiment
载入需要的程辑包:DelayedArray
载入需要的程辑包:matrixStats

载入程辑包:‘matrixStats’

The following objects are masked from ‘package:Biobase’:

    anyMissing, rowMedians

The following object is masked from ‘package:dplyr’:

    count

载入需要的程辑包:BiocParallel

载入程辑包:‘DelayedArray’

The following objects are masked from ‘package:matrixStats’:

    colMaxs, colMins, colRanges, rowMaxs, rowMins, rowRanges

The following object is masked from ‘package:clusterProfiler’:

    simplify

The following objects are masked from ‘package:base’:

    aperm, apply, rowsum


载入程辑包:‘SummarizedExperiment’

The following object is masked from ‘package:Seurat’:

    Assays
# plan("multiprocess",workers = 8)

#冠状动脉

human_coronary_countmatrix <- read.csv("GSE131778_human_coronary_scRNAseq.txt", sep = "\t")
func <- function(s) {
  paste0(strsplit(s, ".", fixed = T)[[1]][2], "_", strsplit(s, ".", fixed = T)[[1]][1])
}
colnames(human_coronary_countmatrix) <- lapply(colnames(human_coronary_countmatrix), func) # 拆分样本

颈动脉斑块 CA dataset1

# 批量读取计数矩阵
# 需要把行名的gene删掉,用vscode修改
count_mats <- list.files("./CA_GSE155512")
count_mats <- count_mats[count_mats != "sampleinfo.txt"]
allList <- lapply(count_mats, function(folder) {
  CreateSeuratObject(
    counts = read.csv(paste0("./CA_GSE155512/", folder), sep = "\t"),
    project = folder, min.cells = 10, min.features = 300
  )
})
# 合并seurat对象
CA_dataset1 <- merge(allList[[1]],
  y = allList[-1], add.cell.ids = count_mats,
  project = "CA_dataset1"
)
rm(allList)

CA_dataset1 <- PercentageFeatureSet(CA_dataset1, pattern = "^MT-", col.name = "percent.mt") %>%
    subset(subset = nFeature_RNA > 600 & nFeature_RNA < 6000 & nCount_RNA > 1000 &  nCount_RNA < 30000) %>%
    SCTransform(vars.to.regress = "percent.mt", verbose = F) %>% 
    RunPCA() %>% FindNeighbors(dims = 1:20) %>% 
    RunUMAP(dims = 1:20) %>% 
    FindClusters(resolution = 0.1)

颈动脉斑块 CA dataset2

CA_dataset2 <- CreateSeuratObject(Read10X("./CA_GSE159677/"), names.field = 2, names.delim = "-",
                                     project = "CA_dataset2", min.cells = 10, min.features = 300) %>% 
    PercentageFeatureSet(pattern = "^MT-", col.name = "percent.mt") %>%
    subset(subset = nFeature_RNA > 600 & nFeature_RNA < 6000 & nCount_RNA > 1000 &  nCount_RNA < 30000) %>%
    SCTransform(vars.to.regress = "percent.mt", verbose = F) %>% 
    RunPCA() %>% FindNeighbors(dims = 1:20) %>% 
    RunUMAP(dims = 1:20) %>% 
    FindClusters(resolution = 0.1)

添加metadata samples存储完整信息,conditions按区域分,groups按病例分

Idents(human_coronary) <- human_coronary$orig.ident
Idents(human_coronary) <- c("1","1","2","2","3","3","4","4")
human_coronary$samples <- Idents(human_coronary)
Idents(human_coronary) <- human_coronary$seurat_clusters

Idents(CA_dataset2) <- CA_dataset2$orig.ident
CA_dataset2 <- RenameIdents(CA_dataset2,'1' = 'AC_1','2' = 'PA_1','3' = 'AC_2','4' = 'PA_2','5' = 'AC_3','6' = 'PA_3')
UMAPPlot(CA_dataset2)

CA_dataset2$sample <- Idents(CA_dataset2)
CA_dataset2 <- RenameIdents(CA_dataset2,'AC_1' = 'AC','PA_1' = 'PA','AC_2'= 'AC','PA_2'= 'PA','AC_3'= 'AC','PA_3'= 'PA')
CA_dataset2$conditions <- Idents(CA_dataset2)
Idents(CA_dataset2) <- CA_dataset2$orig.ident
CA_dataset2 <- RenameIdents(CA_dataset2, '1' = 'sp_1','2' = 'sp_1','3' = 'sp_2','4' = 'sp_2','5' = 'sp_3','6' = 'sp_3')
CA_dataset2$groups <- Idents(CA_dataset2)
Idents(CA_dataset2) <- CA_dataset2$seurat_clusters

保存结果

saveRDS(human_coronary,"human_coronary.rds")
saveRDS(CA_dataset1,"CA_dataset1.rds")
saveRDS(CA_dataset2,"CA_dataset2.rds") #已经经过分组处理了

读取结果

human_coronary <- readRDS("human_coronary.rds")
CA_dataset1 <- readRDS("CA_dataset1.rds")
CA_dataset2 <- readRDS("CA_dataset2.rds") #已经经过分组处理了

修改分群

基质细胞分类

ECs亚群分析 整合

整合算法可能出现负值,运行SCENIC时舍弃了这些异常值

# 提取内皮细胞亚群
ECs_list <- list(subset(CA_dataset1, idents = "Endothelial"), subset(human_coronary, idents = "Endothelial"))

ECs_list <- lapply(X = ECs_list, FUN = function(x) {
  x <- NormalizeData(x)
  x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = 2000)
})
# 需要分析的差异基因
int_features <- SelectIntegrationFeatures(object.list = ECs_list)
# 选择合并的anchor特征
int_anchors <- FindIntegrationAnchors(object.list = ECs_list, anchor.features = int_features)

# 根据anchor合并
ECs_combined <- IntegrateData(anchorset = int_anchors)

DefaultAssay(ECs_combined) <- "integrated"
rm("ECs_list", "int_features", "int_anchors")
multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),human_coronary)

multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),CA_dataset1)

multi_featureplot(c("TNFRSF11B","ACTA2","CNN1","LUM"),CA_dataset2)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgiLi90aWFuZmVuZ1J3cmFwcGVycy5SIikKIyBwbGFuKCJtdWx0aXByb2Nlc3MiLHdvcmtlcnMgPSA4KQpgYGAKCiPlhqDnirbliqjohIkKCmBgYHtyfQpodW1hbl9jb3JvbmFyeV9jb3VudG1hdHJpeCA8LSByZWFkLmNzdigiR1NFMTMxNzc4X2h1bWFuX2Nvcm9uYXJ5X3NjUk5Bc2VxLnR4dCIsIHNlcCA9ICJcdCIpCmZ1bmMgPC0gZnVuY3Rpb24ocykgewogIHBhc3RlMChzdHJzcGxpdChzLCAiLiIsIGZpeGVkID0gVClbWzFdXVsyXSwgIl8iLCBzdHJzcGxpdChzLCAiLiIsIGZpeGVkID0gVClbWzFdXVsxXSkKfQpjb2xuYW1lcyhodW1hbl9jb3JvbmFyeV9jb3VudG1hdHJpeCkgPC0gbGFwcGx5KGNvbG5hbWVzKGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4KSwgZnVuYykgIyDmi4bliIbmoLfmnKwKYGBgCgpgYGB7cn0KaHVtYW5fY29yb25hcnkgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2plY3QgPSAiaHVtYW5fY29yb25hcnkiLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwKSAlPiUgCiAgICBQZXJjZW50YWdlRmVhdHVyZVNldChwYXR0ZXJuID0gIl5NVC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgJT4lCiAgICBzdWJzZXQoc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNjAwICYgbkZlYXR1cmVfUk5BIDwgNjAwMCAmIG5Db3VudF9STkEgPiAxMDAwICYgIG5Db3VudF9STkEgPCAzMDAwMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCnJtKGh1bWFuX2Nvcm9uYXJ5X2NvdW50bWF0cml4KQpmKCJQTFZBUCIsaHVtYW5fY29yb25hcnkpCmBgYAoKCiMg6aKI5Yqo6ISJ5paR5Z2XIENBIGRhdGFzZXQxCmBgYHtyfQojIOaJuemHj+ivu+WPluiuoeaVsOefqemYtQojIOmcgOimgeaKiuihjOWQjeeahGdlbmXliKDmjonvvIznlKh2c2NvZGXkv67mlLkKY291bnRfbWF0cyA8LSBsaXN0LmZpbGVzKCIuL0NBX0dTRTE1NTUxMiIpCmNvdW50X21hdHMgPC0gY291bnRfbWF0c1tjb3VudF9tYXRzICE9ICJzYW1wbGVpbmZvLnR4dCJdCmFsbExpc3QgPC0gbGFwcGx5KGNvdW50X21hdHMsIGZ1bmN0aW9uKGZvbGRlcikgewogIENyZWF0ZVNldXJhdE9iamVjdCgKICAgIGNvdW50cyA9IHJlYWQuY3N2KHBhc3RlMCgiLi9DQV9HU0UxNTU1MTIvIiwgZm9sZGVyKSwgc2VwID0gIlx0IiksCiAgICBwcm9qZWN0ID0gZm9sZGVyLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwCiAgKQp9KQojIOWQiOW5tnNldXJhdOWvueixoQpDQV9kYXRhc2V0MSA8LSBtZXJnZShhbGxMaXN0W1sxXV0sCiAgeSA9IGFsbExpc3RbLTFdLCBhZGQuY2VsbC5pZHMgPSBjb3VudF9tYXRzLAogIHByb2plY3QgPSAiQ0FfZGF0YXNldDEiCikKcm0oYWxsTGlzdCkKCkNBX2RhdGFzZXQxIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KENBX2RhdGFzZXQxLCBwYXR0ZXJuID0gIl5NVC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgJT4lCiAgICBzdWJzZXQoc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNjAwICYgbkZlYXR1cmVfUk5BIDwgNjAwMCAmIG5Db3VudF9STkEgPiAxMDAwICYgIG5Db3VudF9STkEgPCAzMDAwMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCgpgYGAKCgojIOmiiOWKqOiEieaWkeWdlyBDQSBkYXRhc2V0MgpgYGB7cn0KQ0FfZGF0YXNldDIgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KFJlYWQxMFgoIi4vQ0FfR1NFMTU5Njc3LyIpLCBuYW1lcy5maWVsZCA9IDIsIG5hbWVzLmRlbGltID0gIi0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJDQV9kYXRhc2V0MiIsIG1pbi5jZWxscyA9IDEwLCBtaW4uZmVhdHVyZXMgPSAzMDApICU+JSAKICAgIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KHBhdHRlcm4gPSAiXk1ULSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKSAlPiUKICAgIHN1YnNldChzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA2MDAgJiBuRmVhdHVyZV9STkEgPCA2MDAwICYgbkNvdW50X1JOQSA+IDEwMDAgJiAgbkNvdW50X1JOQSA8IDMwMDAwKSAlPiUKICAgIFNDVHJhbnNmb3JtKHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IiwgdmVyYm9zZSA9IEYpICU+JSAKICAgIFJ1blBDQSgpICU+JSBGaW5kTmVpZ2hib3JzKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBSdW5VTUFQKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKYGBgCgoKIyDmt7vliqBtZXRhZGF0YSBzYW1wbGVz5a2Y5YKo5a6M5pW05L+h5oGv77yMY29uZGl0aW9uc+aMieWMuuWfn+WIhu+8jGdyb3Vwc+aMieeXheS+i+WIhgpgYGB7cn0KSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRvcmlnLmlkZW50CklkZW50cyhodW1hbl9jb3JvbmFyeSkgPC0gYygiMSIsIjEiLCIyIiwiMiIsIjMiLCIzIiwiNCIsIjQiKQpodW1hbl9jb3JvbmFyeSRzYW1wbGVzIDwtIElkZW50cyhodW1hbl9jb3JvbmFyeSkKSWRlbnRzKGh1bWFuX2Nvcm9uYXJ5KSA8LSBodW1hbl9jb3JvbmFyeSRzZXVyYXRfY2x1c3RlcnMKCklkZW50cyhDQV9kYXRhc2V0MikgPC0gQ0FfZGF0YXNldDIkb3JpZy5pZGVudApDQV9kYXRhc2V0MiA8LSBSZW5hbWVJZGVudHMoQ0FfZGF0YXNldDIsJzEnID0gJ0FDXzEnLCcyJyA9ICdQQV8xJywnMycgPSAnQUNfMicsJzQnID0gJ1BBXzInLCc1JyA9ICdBQ18zJywnNicgPSAnUEFfMycpClVNQVBQbG90KENBX2RhdGFzZXQyKQoKQ0FfZGF0YXNldDIkc2FtcGxlIDwtIElkZW50cyhDQV9kYXRhc2V0MikKQ0FfZGF0YXNldDIgPC0gUmVuYW1lSWRlbnRzKENBX2RhdGFzZXQyLCdBQ18xJyA9ICdBQycsJ1BBXzEnID0gJ1BBJywnQUNfMic9ICdBQycsJ1BBXzInPSAnUEEnLCdBQ18zJz0gJ0FDJywnUEFfMyc9ICdQQScpCkNBX2RhdGFzZXQyJGNvbmRpdGlvbnMgPC0gSWRlbnRzKENBX2RhdGFzZXQyKQpJZGVudHMoQ0FfZGF0YXNldDIpIDwtIENBX2RhdGFzZXQyJG9yaWcuaWRlbnQKQ0FfZGF0YXNldDIgPC0gUmVuYW1lSWRlbnRzKENBX2RhdGFzZXQyLCAnMScgPSAnc3BfMScsJzInID0gJ3NwXzEnLCczJyA9ICdzcF8yJywnNCcgPSAnc3BfMicsJzUnID0gJ3NwXzMnLCc2JyA9ICdzcF8zJykKQ0FfZGF0YXNldDIkZ3JvdXBzIDwtIElkZW50cyhDQV9kYXRhc2V0MikKSWRlbnRzKENBX2RhdGFzZXQyKSA8LSBDQV9kYXRhc2V0MiRzZXVyYXRfY2x1c3RlcnMKYGBgCgojIOS/neWtmOe7k+aenApgYGB7cn0Kc2F2ZVJEUyhodW1hbl9jb3JvbmFyeSwiaHVtYW5fY29yb25hcnkucmRzIikKc2F2ZVJEUyhDQV9kYXRhc2V0MSwiQ0FfZGF0YXNldDEucmRzIikKc2F2ZVJEUyhDQV9kYXRhc2V0MiwiQ0FfZGF0YXNldDIucmRzIikgI+W3sue7j+e7j+i/h+WIhue7hOWkhOeQhuS6hgpgYGAKCi0tLS0KIyDor7vlj5bnu5PmnpwKYGBge3J9Cmh1bWFuX2Nvcm9uYXJ5IDwtIHJlYWRSRFMoImh1bWFuX2Nvcm9uYXJ5LnJkcyIpCkNBX2RhdGFzZXQxIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQxLnJkcyIpCkNBX2RhdGFzZXQyIDwtIHJlYWRSRFMoIkNBX2RhdGFzZXQyLnJkcyIpICPlt7Lnu4/nu4/ov4fliIbnu4TlpITnkIbkuoYKYGBgCgojIyDkv67mlLnliIbnvqQKYGBge3J9CnVtYXBwbG90KENBX2RhdGFzZXQyLCBzcGxpdC5ieSA9ICJzYW1wbGUiKQp1bWFwcGxvdChDQV9kYXRhc2V0Mixncm91cC5ieSA9ICJncm91cHMiLCBzcGxpdC5ieSA9ICJjb25kaXRpb25zIikKbXVsdGlfZmVhdHVyZXBsb3QoYygiSEVZMSIsIkdKQTUiLCJTRU1BM0ciLCJDWENMMTIiLCJTT1gxNyIsIkNESDUiLCJQRUNBTTEiKSxDQV9kYXRhc2V0MikKbXVsdGlfZmVhdHVyZXBsb3QoYygiQUNLUjEiLCJQTFZBUCIsIklUR0E2IiwiUEVDQU0xIiksQ0FfZGF0YXNldDIpCmBgYApgYGB7cn0KIyB0YWJsZShDQV9kYXRhc2V0MiRzYW1wbGUpCgojIOWFs+azqGNsdXN0ZXIgMy02IEVDCiMgY2x1c3RlciA3IOWfuui0qOe7huiDngoKbXVsdGlfZmVhdHVyZXBsb3QoYygiTFlaIiwiUFRQUkMiLCJDRDY5IiwiRVBDQU0iLCJDREgxIiwiUERHRlJCIiwiQ09MMUEyIiwiUEVDQU0xIiwiQ0xETjUiKSxDQV9kYXRhc2V0MikKCkRvdHBsb3QoYygiTFVNIiwiTU1QMiIsIk1HUCIsIkRDTiIsIk1ZSDExIiwiQUNUQTIiLCJDTk4xIiwiVEFHTE4iKSxDQV9kYXRhc2V0MikgI2NsdXN0ZXIgNyDnu4bog57lj6/ku6XooqvorqTkuLrmmK9tb2R1bGF0ZWQgU01DcwpDQV9kYXRhc2V0MiA8LSBBZGRNb2R1bGVTY29yZShDQV9kYXRhc2V0MixsaXN0KGMoIkxVTSIsIk1NUDIiLCJNR1AiLCJEQ04iKSkpCkNBX2RhdGFzZXQyIDwtIEFkZE1vZHVsZVNjb3JlKENBX2RhdGFzZXQyLGxpc3QoYygiTVlIMTEiLCJBQ1RBMiIsIkNOTjEiLCJUQUdMTiIpKSkKbXVsdGlfZmVhdHVyZXBsb3QoYygiQ2x1c3RlcjEiLCJMVU0iLCJBQ1RBMiIsIlRBR0xOIiksQ0FfZGF0YXNldDIpCm11bHRpX2ZlYXR1cmVwbG90KGMoIk1NUDIiLCJHSkE0IiwiUEVDQU0xIiwiQUNLUjEiKSwgQ0FfZGF0YXNldDIpCm11bHRpX2ZlYXR1cmVwbG90KGMoIk1NUDIiLCJHSkE0IiwiUEVDQU0xIiwiQUNLUjEiKSwgaHVtYW5fY29yb25hcnkpCgpgYGAKIyDln7rotKjnu4bog57liIbnsbsKYGBge3J9Cm11bHRpX2ZlYXR1cmVwbG90KGMoIkxZWiIsIlBUUFJDIiwiQ0Q2OSIsIlBER0ZSQiIsIkNPTDFBMiIsIlBFQ0FNMSIsIkNMRE41IiksIGh1bWFuX2Nvcm9uYXJ5KQptdWx0aV9mZWF0dXJlcGxvdChjKCJBQ1RBMiIsIkZOMSIpLGh1bWFuX2Nvcm9uYXJ5KQp1bWFwcGxvdChodW1hbl9jb3JvbmFyeSkKZHMwIDwtIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gYygnMCcsJzMnLCc0JykpICAjaHVtYW5fY29yIOmAieaLqTAgMyA0ICBDQV9kYXRhc2V0MSDpgInmi6kw77yMNOS9nOS4uuWfuui0qOe7huiDniBDQV9kYXRhc2V0MiDpgInmi6k35ZKMMuS9nOS4uuWfuui0qOe7huiDngojQ0FfZGF0YXNldDIg6YCJ5oupN+WSjDLkvZzkuLrln7rotKjnu4bog54KdW1hcHBsb3QoZHMwLHNwbGl0LmJ5ID0gInNhbXBsZXMiKQoKCnNhdmVSRFMoZHMwLCJkczAucmRzIikKCnNhdmVSRFMoZHMxLCJkczEucmRzIikKCmBgYAoKCgojIEVDc+S6mue+pOWIhuaekCDmlbTlkIgKIyMg5pW05ZCI566X5rOV5Y+v6IO95Ye6546w6LSf5YC877yM6L+Q6KGMU0NFTklD5pe26IiN5byD5LqG6L+Z5Lqb5byC5bi45YC8CmBgYHtyfQojIOaPkOWPluWGheearue7huiDnuS6mue+pApFQ3NfbGlzdCA8LSBsaXN0KHN1YnNldChDQV9kYXRhc2V0MSwgaWRlbnRzID0gIkVuZG90aGVsaWFsIiksIHN1YnNldChodW1hbl9jb3JvbmFyeSwgaWRlbnRzID0gIkVuZG90aGVsaWFsIikpCgpFQ3NfbGlzdCA8LSBsYXBwbHkoWCA9IEVDc19saXN0LCBGVU4gPSBmdW5jdGlvbih4KSB7CiAgeCA8LSBOb3JtYWxpemVEYXRhKHgpCiAgeCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyh4LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCn0pCiMg6ZyA6KaB5YiG5p6Q55qE5beu5byC5Z+65ZugCmludF9mZWF0dXJlcyA8LSBTZWxlY3RJbnRlZ3JhdGlvbkZlYXR1cmVzKG9iamVjdC5saXN0ID0gRUNzX2xpc3QpCiMg6YCJ5oup5ZCI5bm255qEYW5jaG9y54m55b6BCmludF9hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBFQ3NfbGlzdCwgYW5jaG9yLmZlYXR1cmVzID0gaW50X2ZlYXR1cmVzKQoKIyDmoLnmja5hbmNob3LlkIjlubYKRUNzX2NvbWJpbmVkIDwtIEludGVncmF0ZURhdGEoYW5jaG9yc2V0ID0gaW50X2FuY2hvcnMpCgpEZWZhdWx0QXNzYXkoRUNzX2NvbWJpbmVkKSA8LSAiaW50ZWdyYXRlZCIKcm0oIkVDc19saXN0IiwgImludF9mZWF0dXJlcyIsICJpbnRfYW5jaG9ycyIpCmBgYAoKCmBgYHtyfQptdWx0aV9mZWF0dXJlcGxvdChjKCJUTkZSU0YxMUIiLCJBQ1RBMiIsIkNOTjEiLCJMVU0iKSxodW1hbl9jb3JvbmFyeSkKbXVsdGlfZmVhdHVyZXBsb3QoYygiVE5GUlNGMTFCIiwiQUNUQTIiLCJDTk4xIiwiTFVNIiksQ0FfZGF0YXNldDEpCm11bHRpX2ZlYXR1cmVwbG90KGMoIlRORlJTRjExQiIsIkFDVEEyIiwiQ05OMSIsIkxVTSIpLENBX2RhdGFzZXQyKQpgYGAKCgoK